<?php
/**
 * 淘宝开放平台客户端
 *
 * PHP Version 5
 *
 * @package    Project
 * @subpackage Ecga
 * @author     v.k <none@none.com> 
 * @copyright  2010 Xingchangxinda Inc.
 * @version    SVN:$Id: backenduser.php 5128 2011-03-10 09:48:57Z weberliu $
 */
namespace Project\Apps\Ecga\Library;

/**
 * 淘宝开放平台客户端
 *
 * PHP version 5
 *
 * @package    Project
 * @subpackage Ecga
 * @author     v.k <none@none.com> 
 * @copyright  2010 Xingchangxinda Inc.x
 */
class TopClient
{
    public $gateway = '';
    public $appKey = '';
    public $appSecret = '';
    public $session = '';
    
    /**
     * 构造
     *
     * @return void
     */
    public function __construct()
    {
        $this->gateway = 'http://gw.api.taobao.com/router/rest';
    }

    /**
     * 发送请求
     *
     * @param string $method   接口方法标识
     * @param array  $param    请求参数
     * @param string $dataType 返回数据的数据格式，可选值"json", "xml"，默认为"json"
     * 
     * @return mixed 返回类型视$dataType而定
     */
    public function request($method, $param, $dataType = 'json')
    {
        $sysParams = array(
             'app_key' => $this->appKey,
             'method' => $method,
             'format' => $dataType,
             'v' => '2.0',
             'sign_method'=>'md5',
             'timestamp' => date('Y-m-d H:i:s'),
             'session' => $this->session
        );

        $paramArr = array_merge($sysParams, $param);
        $sysParams['sign'] = $this->createSign($paramArr, $this->appSecret);
        //$paramArr['sign'] = $sign;
        $strParam = $this->createStrParam($sysParams);
        $url = $this->gateway . '?' . $strParam;
        
        //$result = file_get_contents($url);
        $result = $this->curl($url, $param);
        if ($dataType == 'json') {
            $result = json_decode($result);
            if (!empty($result->error_response)) {
                $msg = $result->error_response->msg . ' , sub_msg : ' . $result->error_response->sub_msg;
                $code = $result->error_response->code;
                throw new \Exception($msg, $code);
            }
            return $result;
        } else {
            return $result;
        }
    }

    /**
     * Top签名函数
     *
     * @param array  $paramArr  请求参数数组
     * @param string $appSecret appsecret
     * 
     * @return string
     */
    public function createSign($paramArr, $appSecret)
    {
        $sign = $appSecret;
        ksort($paramArr);
        foreach ($paramArr as $key => $val) {
            $sign .= $key.$val;
        }
        $sign .= $appSecret;
        $sign = strtoupper(md5($sign));
        return $sign;
    }

    /**
     * Top组参函数
     *
     * @param array $paramArr 参数列表
     * 
     * @return string
     */
    public function createStrParam($paramArr)
    {
         return http_build_query($paramArr);
    }

    /**
     * 获取客户端实例
     *
     * @return Object 客户端实例
     */
    public static function getInstance()
    {
        static $obj = null;
        
        if ($obj === null) {
            $obj = new TopClient;
        }

        return $obj;
    }
    
    /**
     * cURL方式请求
     *
     * @param string $url        请求地址
     * @param array  $postFields 请求字段
     * 
     * @return object
     */
    protected function curl($url, $postFields = null)
	{
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_FAILONERROR, false);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		if (is_array($postFields) && 0 < count($postFields)) {
			$postBodyString = "";
			$postMultipart = false;
			foreach ($postFields as $k => $v) {
				//判断是不是文件上传 
			    if ("@" != substr($v, 0, 1)) {
					$postBodyString .= "$k=" . urlencode($v) . "&"; 
				} else {
					//文件上传用multipart/form-data，否则用www-form-urlencoded
				    $postMultipart = true;
				}
			}
			unset($k, $v);
			curl_setopt($ch, CURLOPT_POST, true);
			if ($postMultipart) {
				curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
			} else {
				curl_setopt($ch, CURLOPT_POSTFIELDS, substr($postBodyString, 0, -1));
			}
		}
		$reponse = curl_exec($ch);
		if (curl_errno($ch)) {
			throw new \Exception(curl_error($ch), 0);
		} else {
			$httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
			if (200 !== $httpStatusCode) {
				throw new \Exception($reponse, $httpStatusCode);
			}
		}
		curl_close($ch);
		return $reponse;
	}
}